﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace SupermarketSalesModel
{
    [Serializable]
    public abstract class Person
    {
        protected String idCard;  //DNI = identity card
        protected String name;
        protected String lastname;
        protected DateTime bornDate;
        protected DateTime registerDate;
        protected int telephoneNumber;
        protected String email;
        protected int status;

        public Person(String idCard, String name, String lastname,
                      DateTime bornDate, DateTime registerDate,
                      int tnumber, String email)
        {
            this.idCard = idCard;
            this.name = name;
            this.lastname = lastname;
            this.bornDate = bornDate;
            this.registerDate = registerDate;
            this.telephoneNumber = tnumber;
            this.email = email;
            this.status = 1;
        }

        public String IdCard
        {
            get { return idCard; }
            set { idCard = value; }
        }
        

        public String Name
        {
            get { return name; }
            set { name = value; }
        }
        

        public String Lastname
        {
            get { return lastname; }
            set { lastname = value; }
        }
        

        public DateTime BornDate
        {
            get { return bornDate; }
            set { bornDate = value; }
        }
        

        public DateTime RegisterDate
        {
            get { return registerDate; }
            set { registerDate = value; }
        }
        

        public int TelephoneNumber
        {
            get { return telephoneNumber; }
            set { telephoneNumber = value; }
        }
        

        public String Email
        {
            get { return email; }
            set { email = value; }
        }

        public int Status
        {
            get { return status; }
            set { status = value; }
        }

        public Person() { }
        
    }

    [Serializable]
    public class Client : Person
    {
        private int idClient;

        public int IdClient
        {
            get { return idClient; }
            set { idClient = value; }
        }
        private String cardNumber;

        public String CardNumber
        {
            get { return cardNumber; }
            set { cardNumber = value; }
        }
        private String category;

        public String Category
        {
            get { return category; }
            set { category = value; }
        }

        private int points;

        public int Points
        {
            get { return points; }
            set { points = value; }
        }

        public Client(String idCard, String name, String lastname,
                      DateTime bornDate, DateTime registerDate,
                      int telnum, String email, int idClient, String cardNumber, 
                      String category)
            : base(idCard, name, lastname, bornDate, 
                               registerDate, telnum, email)
        {
            this.idClient = idClient;
            this.cardNumber = cardNumber;
            this.category = category;
            this.points = 0;
        }

        public override String ToString()
        {
            return name + " " + lastname + " ";
        }

        public Client() {}
    }

    [Serializable]
    public class Salesclerk : Person
    {
        private int idClerk;

        public int IdClerk
        {
            get { return idClerk; }
            set { idClerk = value; }
        }
        private String observations;

        public String Observations
        {
            get { return observations; }
            set { observations = value; }
        }

        public Salesclerk(String idCard, String name, String lastname,
                      DateTime bornDate, DateTime registerDate,
                      int telnum, String email, int idClerk, String observations) 
            : base(idCard, name, lastname, bornDate, 
                               registerDate, telnum, email)
        {
            this.idClerk = idClerk;
            this.observations = observations;
        }

        public override String ToString()
        {
            return name + " " + lastname;
        }
        public Salesclerk()
        {

        }
    }

    [Serializable]
    public class Product
    {

        private int id;
        private String description;
        private String ean;
        private double basePrice;
        private String brand;
        private String type;
        private int status;


        public int Id
        {
            get { return id; }
            set { id = value; }
        }



        public String Description
        {
            get { return description; }
            set { description = value; }
        }


        public String Ean
        {
            get { return ean; }
            set { ean = value; }
        }


        public double BasePrice
        {
            get { return basePrice; }
            set { basePrice = value; }
        }


        public String Brand
        {
            get { return brand; }
            set { brand = value; }
        }


        public String Type
        {
            get { return type; }
            set { type = value; }
        }

        public int Status
        {
            get { return status; }
            set { status = value; }
        }
        
        public override String ToString()
        {
            return description + " - " + brand;
        }

        public Product(int id, String description, String ean, double baseprice,
                       String brand, String type)
        {
            this.id = id;
            this.description = description;
            this.ean = ean;
            this.basePrice = baseprice;
            this.brand = brand;
            this.type = type;
            this.status = 1;
        }

        public Product() { }

    }

    [Serializable]
    public class CashRegister
    {
        private int id;

        public int Id
        {
            get { return id; }
            set { id = value; }
        }
        private String description;

        public String Description
        {
            get { return description; }
            set { description = value; }
        }
        private int status;

        public int Status
        {
            get { return status; }
            set { status = value; }
        }

        public CashRegister( int id, string description)
        {
            this.id = id;
            this.description = description;
            this.status = 1;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(id + ": ");
            sb.Append(description + " - ");

            if (status == 0)
            {
                sb.Append("Inactiva");
            }
            else
            {
                sb.Append("Activa");
            }
            return sb.ToString();
        }
        public CashRegister()
        {

        }
    }

    [Serializable]
    public class SalesDetail
    {
        private int id;

        private int idSale;

        public int IdSale
        {
            get { return idSale; }
            set { idSale = value; }
        }

        public int Id
        {
            get { return id; }
            set { id = value; }
        }
        

        
        private Product product;

        public Product Product
        {
            get { return product; }
            set { product = value; }
        }
        private int quantity;

        public int Quantity
        {
            get { return quantity; }
            set { quantity = value; }
        }
        private double subTotal;

        public double SubTotal
        {
            get { return subTotal; }
            set { subTotal = value; }
        }

        private CreditNote creditNote;

        public CreditNote CreditNote
        {
            get { return creditNote; }
            set { creditNote = value; }
        }



        public override String ToString()
        {
            return quantity + "\t" + product.ToString() + "\t" + subTotal;
        }


        public SalesDetail()
        {

        }
    }

    [Serializable]
    public class Sale
    {
        public const double IGV = 0.18;
        private int id;
        private DateTime saleDate;
        private Salesclerk clerk;
        private Client client;
        private CashRegister cashReg;        
        private List<SalesDetail> details = new List<SalesDetail>();
        private double subTotalAmount;
        private double totalAmount;
        private int wonPoints = 0; //Cada 7 soles de compra es un punto
        private double paidAmount;
        private int flag;

        public int Flag
        {
            get { return flag; }
            set { flag = value; }
        }



        public double PaidAmount
        {
            get { return paidAmount; }
            set { paidAmount = value; }
        }


        public int Id
        {
            get { return id; }
            set { id = value; }
        }
        

        public DateTime SaleDate
        {
            get { return saleDate; }
            set { saleDate = value; }
        }
       

        public Salesclerk Clerk
        {
            get { return clerk; }
            set { clerk = value; }
        }
       

        public Client Client
        {
            get { return client; }
            set { client = value; }
        }
        

        public CashRegister CashReg
        {
            get { return cashReg; }
            set { cashReg = value; }
        }
        

        public List<SalesDetail> Details
        {
            get { return details; }
            set { details = value; }
        }
        

        public double SubTotalAmount
        {
            get { return subTotalAmount; }
            set { subTotalAmount = value; }
        }
        

        public double TotalAmount
        {
            get { return totalAmount; }
            set { totalAmount = value; }
        }

        public int WonPoints
        {
            get { return wonPoints; }
            set { wonPoints = value; }
        }

        public void addDetail(Product p, int quantity)
        {
            SalesDetail sd = new SalesDetail();
            sd.Id = (details.Count +1 );
            sd.Product = p;
            sd.IdSale = this.Id;
            sd.Quantity = quantity;
            sd.SubTotal = quantity * p.BasePrice;
            details.Add(sd);
            TotalAmount += sd.SubTotal;

        }

        public void finish(double paidAmount)
        {
       
            wonPoints = (int)(this.TotalAmount / 7);
            
            this.paidAmount = paidAmount;
            
            if (client != null)
                client.Points += wonPoints;

            //SIN IGV
            subTotalAmount = totalAmount / (1 + IGV);
           
        }
        public Sale()
        {

        }

    }
    
    [Serializable]
    public class CNDetail
    {

        private int id;
        private Product product;
        private int quantity;

        private double usedPrice;
        private double subTotal;

        private int cnId;

        public int CnId
        {
            get { return cnId; }
            set { cnId = value; }
        }

        public int Id
        {
            get { return id; }
            set { id = value; }
        }

        public Product Product
        {
            get { return product; }
            set { product = value; }
        }

        public int Quantity
        {
            get { return quantity; }
            set { quantity = value; }
        }


        public double UsedPrice
        {
            get { return usedPrice; }
            set { usedPrice = value; }
        }

        public double SubTotal
        {
            get { return subTotal; }
            set { subTotal = value; }
        }

       

        public override String ToString()
        {
            return "\t" + quantity + "\t" + product.ToString() + "\t" + subTotal;
        }

        public CNDetail()
        {

        }
    }

    [Serializable]
    public class CreditNote
    {
        private int id;
        private Sale sale;
        private double amount;
        private DateTime registerDate;
        private List<CNDetail> details = new List<CNDetail>();
        private int flag;

        public int Flag
        {
            get { return flag; }
            set { flag = value; }
        }

        public CreditNote(int id, Sale sale)
        {
            this.id = id;
            this.sale = sale;
            this.amount = 0;
            this.registerDate = DateTime.Now;
        }

        public void addDetail(Product p, int quantity, double origPrice)
        {   
            CNDetail cd = new CNDetail();
            cd.Id = (details.Count + 1);
            cd.Product = p;
            cd.CnId = this.Id;
            cd.Quantity = quantity;
            cd.SubTotal = quantity * origPrice;
            cd.UsedPrice = origPrice;

            details.Add(cd);
            amount += cd.SubTotal;

        }

        public int Id
        {
            get { return id; }
            set { id = value; }
        }
        

        public Sale Sale
        {
            get { return sale; }
            set { sale = value; }
        }
        

        public double Amount
        {
            get { return amount; }
            set { amount = value; }
        }
        

        public DateTime RegisterDate
        {
            get { return registerDate; }
            set { registerDate = value; }
        }

        public List<CNDetail> Details
        {
            get { return details; }
            set { details = value; }
        }

        public CreditNote()
        {

        }

    }

}
